//    The breaker of the screen control
//    Copyright (C) 2025  VekarisWesion
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <https://www.gnu.org/licenses/>.

#include <windows.h>
#include <vector>
#include <algorithm>
#include <TlHelp32.h>
#include <iostream>
#include <fstream>

// 用户设定 
static const wchar_t* hostWindowName = L"Host Window";  // 默认宿主窗口名称
static const char* targetWindowClass = "DIBFullViewClass";  // 默认目标窗口类名


// 全局变量

static const wchar_t* className = L"HostWindowClass";
bool topMost = true;
RECT g_rectWindowBeforeFullscreen = {0};
bool g_bFullscreen = false;
bool g_gotTarget = false;
bool g_Debug = false; 
HWND hTarget = 0;
HWND hHost = 0;

// 宿主窗口消息处理
void db_o(std::string s){
	using namespace std;
	if (g_Debug){
		cout << endl;
		cout << "[Debug]" << s << endl;
		cout << "(BKR) $";
	}
	return;
} 
LRESULT CALLBACK HostWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_SIZE: {
    	InvalidateRect(hTarget, NULL, TRUE);
		UpdateWindow(hTarget);
        if (IsWindow(hTarget)&&g_gotTarget) {
            RECT rect;
            GetClientRect(hWnd, &rect);
            SetWindowPos(hTarget, NULL, 0, 0, rect.right, rect.bottom, SWP_NOZORDER | SWP_FRAMECHANGED);
        }
        SetWindowPos(hHost, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
        break;

    }
    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE) {
            g_bFullscreen = !g_bFullscreen;
            
            if (g_bFullscreen) {
                GetWindowRect(hWnd, &g_rectWindowBeforeFullscreen);
                SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
                SetWindowPos(hWnd, HWND_TOP, 
                            0, 0, 
                            GetSystemMetrics(SM_CXSCREEN), 
                            GetSystemMetrics(SM_CYSCREEN), 
                            SWP_FRAMECHANGED);
            } else {
                SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
                SetWindowPos(hWnd, NULL, 
                            g_rectWindowBeforeFullscreen.left, 
                            g_rectWindowBeforeFullscreen.top, 
                            g_rectWindowBeforeFullscreen.right - g_rectWindowBeforeFullscreen.left, 
                            g_rectWindowBeforeFullscreen.bottom - g_rectWindowBeforeFullscreen.top, 
                            SWP_FRAMECHANGED | SWP_NOZORDER);
            }
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

// 创建宿主窗口
HWND CreateHostWindow(HWND hTarget) {
    // 创建窗口
    HWND hHost = CreateWindowExW(
        0, className, hostWindowName,
        WS_POPUP | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        800, 600, NULL, NULL, GetModuleHandle(NULL), NULL
    );
    // 存储目标窗口句柄
    SetWindowLongPtr(hHost, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(hTarget));
    return hHost;
}


// 嵌入目标窗口到宿主
void EmbedWindow() {
    if (!IsWindow(hTarget) || !IsWindowVisible(hTarget) || GetParent(hTarget) != NULL)
        return;

    // 修改窗口样式
    LONG_PTR style = GetWindowLongPtr(hTarget, GWL_STYLE);
    LONG_PTR exStyle = GetWindowLongPtr(hTarget, GWL_EXSTYLE);

    // 移除不需要的样式
    style &= ~(WS_POPUP);
    style |= WS_CHILD;

    // 移除顶层窗口样式
    exStyle &= ~(WS_EX_TOPMOST);

    SetWindowLongPtr(hTarget, GWL_STYLE, style);
    SetWindowLongPtr(hTarget, GWL_EXSTYLE, exStyle);

    // 设置父子关系
    SetParent(hTarget, hHost);

    // 调整尺寸
    InvalidateRect(hTarget, NULL, TRUE);
	UpdateWindow(hTarget);
    RECT rect;
    GetClientRect(hHost, &rect);
    SetWindowPos(hTarget, NULL, rect.left, rect.top, rect.right, rect.bottom, SWP_NOZORDER | SWP_FRAMECHANGED);
    SetWindowPos(hHost, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
    
}

DWORD WINAPI conIn(LPVOID lpParameter) {
    using namespace std;
    
    cout << "ScreenControlBreaker-alpha-1.1.1  Copyright (C) 2025  VekarisWesion" << endl;
    cout << "This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'." << endl;
    cout << "This is free software, and you are welcome to redistribute it" << endl;
    cout << "under certain conditions; type `show c' for details." << endl;
    cout << endl;
        
    cout << "Command options:" << endl;
    cout << "  PW       - View project webpage" << endl;
    cout << "  top      - Toggle window top-most state" << endl;
    cout << "  debug    - Toggle debug mode" << endl;
    cout << "Press Ctrl + C to exit." << endl;
    cout << endl;
    
    while (true){
        cout << "(BKR) $";
        string cmd;
        cin >> cmd;
        if (cmd == "PW"){
            system("start https://gitee.com/vekariswesion/character-world-screen-control-breaker");
            cout << "Success" << endl;
        } else if (cmd == "top"){
            topMost = !topMost;
            cout << "Success" << ' ' << (topMost ? "On" : "Off") << endl;
        } else if (cmd == "debug") {
            g_Debug = !g_Debug;
            cout << "Success" << ' ' << (g_Debug ? "Off" : "On") << endl;
        } else {
        	cout << "Unknown command" << endl;
		}
        Sleep(300);
    }
    return 0;
}

DWORD WINAPI findWD(LPVOID lpParameter) {
    while (true){
        while (!IsWindow(hTarget)) {
            hTarget = FindWindowA(targetWindowClass, "");
            Sleep(50);
        }
        db_o("finded");
        g_gotTarget = true;
        ShowWindow(hHost, SW_SHOW);
        EmbedWindow();
        while(g_gotTarget){
            Sleep(250);
        }
    }
    return 0;
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEXW wc = { sizeof(WNDCLASSEX) };
    wc.lpfnWndProc = HostWndProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.lpszClassName = className;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    RegisterClassExW(&wc);
    CreateThread(NULL, 0, conIn, NULL, 0, NULL);
    hHost = CreateHostWindow(hTarget);
    ShowWindow(hHost, SW_HIDE);
    CreateThread(NULL, 0, findWD, NULL, 0, NULL);
    
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
	    TranslateMessage(&msg);
	    DispatchMessage(&msg);
	    
	    if (g_gotTarget) {
	        if (!IsWindow(hTarget)) {
	            g_gotTarget = false;
	            if (IsWindow(hHost)) {
	                ShowWindow(hHost, SW_HIDE);
	            }
	            continue;
	        }
	        
	        if (IsWindow(hHost)) {
	            SetWindowPos(hHost, (topMost?HWND_TOPMOST:HWND_NOTOPMOST), 
	                        0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
	        }
	        
	        if (IsWindow(hTarget) && IsWindow(hHost)) {
	            LONG_PTR style = GetWindowLongPtr(hTarget, GWL_STYLE);
	            if (style != 0) {  // 检查GetWindowLongPtr是否成功
	                style &= ~WS_POPUP;
	                style |= WS_CHILD;
	                SetWindowLongPtr(hTarget, GWL_STYLE, style);
	                SetWindowPos(hTarget, HWND_NOTOPMOST, 0, 0, 0, 0, 
	                            SWP_NOMOVE | SWP_NOSIZE);
	                
	                if (GetParent(hTarget) != hHost) {
	                    SetParent(hTarget, hHost);
	                }
	            }
	        }
	    }
	}
    return 0;
}
